package com.power.test.model.json;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import com.power.test.model.IEnum;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * Json Helper 采用jackjson
 */
public class JsonHelper {
	/**
	 * 序列化成字符串
	 */
	public static <T> String toJsonString(T model) {
		if (model == null) return "";
		try {
			ObjectMapper mapper = getMapper();
			return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(model);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		return "";
	}

	/**
	 * 返序列化成对象
	 */
	public static <T> T toBean(String jsonString, Class<T> clazz) {
		try {
			if (StringUtils.isBlank(jsonString)) return null;
			ObjectMapper mapper = getMapper();
			return mapper.readValue(jsonString, clazz);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 返序列化成对象集合
	 */
	public static <T> List<T> toList(String jsonString, Class<T> clazz) {
		//返回集合
		List<T> result = new ArrayList<>();

		try {
			ObjectMapper mapper = getMapper();
			CollectionType listType = mapper.getTypeFactory().constructCollectionType(ArrayList.class, clazz);
			result = mapper.readValue(jsonString, listType);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 获取mapper
	 *
	 * @return
	 */
	public static ObjectMapper getMapper() {
		ObjectMapper objectMapper = new ObjectMapper();
		SimpleModule simpleModule = new SimpleModule();

		//序列化枚举
		simpleModule.addSerializer(IEnum.class, new EnumSerializer());
		//序列化时间LocalDateTime
		simpleModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
		//序列化时间LocalDate
		simpleModule.addSerializer(LocalDate.class, new LocalDateSerializer());
		//序列化时间LocalDate
		simpleModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
		//序列化时间LDate
//		simpleModule.addSerializer(Date.class, new DateSerializer());
		//simpleModule.addSerializer(Boolean.class, new BooleanSerializer());
		//忽略null字段
		//objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
		//忽略大小写
		objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);

		//反序列化
		//允许json属性名不使用双引号
		objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
		//日期序列化
		objectMapper.configure(SerializationFeature.WRITE_DATES_WITH_ZONE_ID, false);
		//忽略不存在字段
		objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		//simpleModule.addDeserializer(String.class, new StringDeserializer());
		//反序列化时间LocalDateTime
		simpleModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
		//反序列化时间LocalDate
		simpleModule.addDeserializer(LocalDate.class, new LocalDateDeserializer());
		//反序列化时间LocalDate
		simpleModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
		//反序列化时间Date
//		simpleModule.addDeserializer(Date.class, new DateDeserializer());
		//反序列化枚举
		simpleModule.addDeserializer(Enum.class, new EnumDeserializer());
		//simpleModule.addDeserializer(Boolean.class, new BooleanDeserializer());
		objectMapper.registerModule(simpleModule);
		return objectMapper;
	}

	/**
	 * 序列化方式转换对象（单对象）
	 * @param map 要转换的对象
	 * @param type 转换的对象类型
	 * @param <T> 要转换的对象类型
	 * @param <R> 转换对象的类型
	 * @return 转换后的对象
	 */
	public static <T, R> R  toObj(T map, Class<R> type) {
		String jsonStr = JsonHelper.toJsonString(map);
		return JsonHelper.toBean(jsonStr, type);
	}

	/**
	 * 序列化方式转换对象（集合）
	 * @param map 要转换的对象
	 * @param type 转换的对象类型
	 * @param <T> 要转换的对象类型
	 * @param <R> 转换对象的类型
	 * @return 转换后的对象
	 */
	public static <T, R> List<R>  toObjList(T map, Class<R> type) {
		String jsonStr = JsonHelper.toJsonString(map);
		return JsonHelper.toList(jsonStr, type);
	}
}
